package com.jse;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Date;

/**
 * 提供了一组静态方法用于将对象转换为不同的基本数据类型及其包装类。
 */
public class Casts {

    /**
     * 将对象转换为 Integer 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Integer 对象，如果对象为 null 则返回 null
     */
    public static Integer toInt(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return n.intValue();
        return Integer.valueOf(o.toString());
    }

    /**
     * 将对象转换为 Short 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Short 对象，如果对象为 null 则返回 null
     */
    public static Short toShort(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return n.shortValue();
        return Short.valueOf(o.toString());
    }

    /**
     * 将对象转换为 Long 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Long 对象，如果对象为 null 则返回 null
     */
    public static Long toLong(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return n.longValue();
        return Long.valueOf(o.toString());
    }

    /**
     * 将对象转换为 Float 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Float 对象，如果对象为 null 则返回 null
     */
    public static Float toFloat(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return n.floatValue();
        return Float.valueOf(o.toString());
    }

    /**
     * 将对象转换为 Double 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Double 对象，如果对象为 null 则返回 null
     */
    public static Double toDouble(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return n.doubleValue();
        return Double.valueOf(o.toString());
    }

    /**
     * 将对象转换为 Byte 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Byte 对象，如果对象为 null 则返回 null
     */
    public static Byte toByte(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return n.byteValue();
        return Byte.valueOf(o.toString());
    }

    /**
     * 将对象转换为 Character 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Character 对象，如果对象为 null 则返回 null
     */
    public static Character toChar(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return Character.valueOf((char) n.intValue());
        return Character.valueOf(o.toString().charAt(0));
    }

    /**
     * 将对象转换为 Boolean 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 Boolean 对象，如果对象为 null 则返回 null
     */
    public static Boolean toBoolean(Object o) {
        if (o == null) return null;
        else if (o instanceof Boolean b) return b;
        else if (o instanceof Number n) return n.intValue() != 0; // 非零值为 true，0 则为 false
        return Boolean.valueOf(o.toString());
    }

    /**
     * 将对象转换为 String 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 String 对象，如果对象为 null 则返回 null
     */
    public static String toString(Object o) {
        if (o == null) return null;
        return o.toString();
    }

    /**
     * 将对象转换为 BigInteger 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 BigInteger 对象，如果对象为 null 则返回 null
     */
    public static BigInteger toBigInteger(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return BigInteger.valueOf(n.longValue());
        return new BigInteger(o.toString());
    }

    /**
     * 将对象转换为 BigDecimal 类型。
     * 
     * @param o 要转换的对象
     * @return 转换后的 BigDecimal 对象，如果对象为 null 则返回 null
     */
    public static BigDecimal toBigDecimal(Object o) {
        if (o == null) return null;
        else if (o instanceof Number n) return BigDecimal.valueOf(n.doubleValue());
        return new BigDecimal(o.toString());
    }

    /**
     * 将对象转换为目标类型。
     * 
     * @param o 要转换的对象
     * @param target 目标类型
     * @param <T> 泛型类型
     * @return 转换后的对象，如果对象为 null 或目标类型不匹配则返回 null
     */
    public static <T> Object to(Object o, Class<T> target) {
        if (target == null) return null;
        if (target.isPrimitive() && o == null) {
            if (boolean.class == target) return Boolean.FALSE;
            return 0;
        }
        if (o == null) return null;
        var oc = o.getClass();
        if (target == oc) return o;
        if (target.isAssignableFrom(oc)) return o; // 相等或子类无需转换
        if (target == int.class || target == Integer.class) return toInt(o);
        if (target == short.class || target == Short.class) return toShort(o);
        if (target == long.class || target == Long.class) return toLong(o);
        if (target == float.class || target == Float.class) return toFloat(o);
        if (target == double.class || target == Double.class) return toDouble(o);
        if (target == byte.class || target == Byte.class) return toByte(o);
        if (target == char.class || target == Character.class) return toChar(o);
        if (target == boolean.class || target == Boolean.class) return toBoolean(o);
        if (target == String.class) return o.toString();
        if (target == Date.class) return Times.parse(o);
        if (target.isArray()) {
            var c = target.getComponentType();
            if (oc.isArray()) {
                Object[] l = (Object[]) o;
                int len = l.length;
                Object[] arr = (Object[]) Array.newInstance(c, len);
                for (int i = 0; i < len; i++) {
                    arr[i] = to(l[i], c);
                }
                return arr;
            } else if (o instanceof Collection l) {
                int len = l.size();
                Object[] arr = (Object[]) Array.newInstance(c, len);
                int i = 0;
                for (Object v : l) {
                    arr[i] = to(v, c);
                    i++;
                }
                return arr;
            } else {
                System.out.println(o.getClass() + " 不支持");
                return null;
            }
        }
        return null;
    }

    /**
     * 主方法用于测试转换功能。
     * 
     * @param args 命令行参数
     */
    public static void main(String[] args) {
//      String[] s = (String[]) to(Lang.ofSet("a", true, 2), String[].class);
//      System.out.println(Arrays.toString(s));
        System.out.println(Boolean.valueOf("on"));
    }
}